package esmp.jtt808.model;

import common.utils.DataPackUtil;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by dave on 18-7-20 下午5:58.
 */
public class TerminalParam implements Encoder, Decoder<TerminalParam> {
    private int paramCount;
    private Byte terminalHeartbeat;
    private Short tcpRespTimeout;
    private Byte tcpRetry;
    private Short udpRespTimeout;
    private Byte udpRetry;
    private Short smsRespTimeout;
    private Byte smsRetry;
    private String mainServerApn;
    private String mainServerUser;
    private String mainServerPassword;
    private String mainServerAddress;
    private String backupsServerApn;
    private String backupsServerUser;
    private String backupsServerPassword;
    private String backupsServerAddress;
    private Short serverTcpPort;
    private Short serverUdpPort;

    @Override
    public byte[] encode() {
        paramCount = 0;
        List<Byte> bytes = new ArrayList<>(256);
        bytes.add((byte) 0);
        addParam(bytes, Param.terminalHeartbeat, terminalHeartbeat);
        addParam(bytes, Param.tcpRespTimeout, tcpRespTimeout);
        addParam(bytes, Param.tcpRetry, tcpRetry);
        addParam(bytes, Param.udpRespTimeout, udpRespTimeout);
        addParam(bytes, Param.udpRetry, udpRetry);
        addParam(bytes, Param.smsRespTimeout, smsRespTimeout);
        addParam(bytes, Param.smsRetry, smsRetry);
        addParam(bytes, Param.mainServerApn, mainServerApn);
        addParam(bytes, Param.mainServerUser, mainServerUser);
        addParam(bytes, Param.mainServerPassword, mainServerPassword);
        addParam(bytes, Param.mainServerAddress, mainServerAddress);
        addParam(bytes, Param.backupsServerApn, backupsServerApn);
        addParam(bytes, Param.backupsServerUser, backupsServerUser);
        addParam(bytes, Param.backupsServerPassword, backupsServerPassword);
        addParam(bytes, Param.backupsServerAddress, backupsServerAddress);
        addParam(bytes, Param.serverTcpPort, serverTcpPort);
        addParam(bytes, Param.serverUdpPort, serverUdpPort);
        bytes.set(0, (byte) paramCount);
        return DataPackUtil.byteListToArray(bytes);
    }

    @Override
    public TerminalParam decode(byte[] bytes, int start, int end) {
        paramCount = bytes[start];
        for (int i = start + 1; i < paramCount;) {
            int code = DataPackUtil.readWord(bytes, i);
            Param p = Param.of(code);
            switch (p) {
                case terminalHeartbeat:
                    terminalHeartbeat = bytes[i + 3];
                    i += 4;
                    break;
                case tcpRespTimeout:
                    tcpRespTimeout = (short) DataPackUtil.readWord(bytes, i + 3);
                    i += 5;
                    break;
                case tcpRetry:
                    tcpRetry = bytes[i + 3];
                    i += 4;
                    break;
                case udpRespTimeout:
                    udpRespTimeout = (short) DataPackUtil.readWord(bytes, i + 3);
                    i += 5;
                    break;
                case udpRetry:
                    udpRetry = bytes[i + 3];
                    i += 4;
                    break;
                case smsRespTimeout:
                    smsRespTimeout = (short) DataPackUtil.readWord(bytes, i + 3);
                    i += 5;
                    break;
                case smsRetry:
                    smsRetry = bytes[i + 3];
                    i += 4;
                    break;
                case mainServerApn:
                    mainServerApn = DataPackUtil.bytesToString(bytes, i + 3, bytes[i + 2]);
                    i += bytes[i + 2] + 3;
                    break;
                case mainServerUser:
                    mainServerUser = DataPackUtil.bytesToString(bytes, i + 3, bytes[i + 2]);
                    i += bytes[i + 2] + 3;
                    break;
                case mainServerPassword:
                    mainServerPassword = DataPackUtil.bytesToString(bytes, i + 3, bytes[i + 2]);
                    i += bytes[i + 2] + 3;
                    break;
                case mainServerAddress:
                    mainServerAddress = DataPackUtil.bytesToString(bytes, i + 3, bytes[i + 2]);
                    i += bytes[i + 2] + 3;
                    break;
                case backupsServerApn:
                    backupsServerApn = DataPackUtil.bytesToString(bytes, i + 3, bytes[i + 2]);
                    i += bytes[i + 2] + 3;
                    break;
                case backupsServerUser:
                    backupsServerUser = DataPackUtil.bytesToString(bytes, i + 3, bytes[i + 2]);
                    i += bytes[i + 2] + 3;
                    break;
                case backupsServerPassword:
                    backupsServerPassword = DataPackUtil.bytesToString(bytes, i + 3, bytes[i + 2]);
                    i += bytes[i + 2] + 3;
                    break;
                case backupsServerAddress:
                    backupsServerAddress = DataPackUtil.bytesToString(bytes, i + 3, bytes[i + 2]);
                    i += bytes[i + 2] + 3;
                    break;
                case serverTcpPort:
                    serverTcpPort = (short) DataPackUtil.readWord(bytes, i + 3);
                    i += 5;
                    break;
                case serverUdpPort:
                    serverUdpPort = (short) DataPackUtil.readWord(bytes, i + 3);
                    i += 5;
                    break;
            }
        }
        return this;
    }

    public void addParam(List<Byte> bytes, Param param, Byte b) {
        if (b != null) {
            paramCount++;
            bytes.addAll(DataPackUtil.getWordBytes(param.getCode()));
            bytes.add((byte) 1);
            bytes.add(b);
        }
    }

    public void addParam(List<Byte> bytes, Param param, Short s) {
        if (s != null) {
            paramCount++;
            bytes.addAll(DataPackUtil.getWordBytes(param.getCode()));
            bytes.add((byte) 1);
            bytes.addAll(DataPackUtil.getWordBytes(s));
        }
    }

    public void addParam(List<Byte> bytes, Param param, String s) {
        if (s != null) {
            paramCount++;
            List<Byte> list;
            try {
                list = DataPackUtil.byteArrayToList(s.getBytes(DataPackUtil.DEFAULT_CHARSET_GBK));
            } catch (UnsupportedEncodingException e) {
                list = Collections.emptyList();
            }
            bytes.addAll(DataPackUtil.getWordBytes(param.getCode()));
            bytes.add((byte) list.size());
            bytes.addAll(list);
        }
    }

    public int getParamCount() {
        return paramCount;
    }

    public void setParamCount(int paramCount) {
        this.paramCount = paramCount;
    }

    public Byte getTerminalHeartbeat() {
        return terminalHeartbeat;
    }

    public void setTerminalHeartbeat(Byte terminalHeartbeat) {
        this.terminalHeartbeat = terminalHeartbeat;
    }

    public Short getTcpRespTimeout() {
        return tcpRespTimeout;
    }

    public void setTcpRespTimeout(Short tcpRespTimeout) {
        this.tcpRespTimeout = tcpRespTimeout;
    }

    public Byte getTcpRetry() {
        return tcpRetry;
    }

    public void setTcpRetry(Byte tcpRetry) {
        this.tcpRetry = tcpRetry;
    }

    public Short getUdpRespTimeout() {
        return udpRespTimeout;
    }

    public void setUdpRespTimeout(Short udpRespTimeout) {
        this.udpRespTimeout = udpRespTimeout;
    }

    public Byte getUdpRetry() {
        return udpRetry;
    }

    public void setUdpRetry(Byte udpRetry) {
        this.udpRetry = udpRetry;
    }

    public Short getSmsRespTimeout() {
        return smsRespTimeout;
    }

    public void setSmsRespTimeout(Short smsRespTimeout) {
        this.smsRespTimeout = smsRespTimeout;
    }

    public Byte getSmsRetry() {
        return smsRetry;
    }

    public void setSmsRetry(Byte smsRetry) {
        this.smsRetry = smsRetry;
    }

    public String getMainServerApn() {
        return mainServerApn;
    }

    public void setMainServerApn(String mainServerApn) {
        this.mainServerApn = mainServerApn;
    }

    public String getMainServerUser() {
        return mainServerUser;
    }

    public void setMainServerUser(String mainServerUser) {
        this.mainServerUser = mainServerUser;
    }

    public String getMainServerPassword() {
        return mainServerPassword;
    }

    public void setMainServerPassword(String mainServerPassword) {
        this.mainServerPassword = mainServerPassword;
    }

    public String getMainServerAddress() {
        return mainServerAddress;
    }

    public void setMainServerAddress(String mainServerAddress) {
        this.mainServerAddress = mainServerAddress;
    }

    public String getBackupsServerApn() {
        return backupsServerApn;
    }

    public void setBackupsServerApn(String backupsServerApn) {
        this.backupsServerApn = backupsServerApn;
    }

    public String getBackupsServerUser() {
        return backupsServerUser;
    }

    public void setBackupsServerUser(String backupsServerUser) {
        this.backupsServerUser = backupsServerUser;
    }

    public String getBackupsServerPassword() {
        return backupsServerPassword;
    }

    public void setBackupsServerPassword(String backupsServerPassword) {
        this.backupsServerPassword = backupsServerPassword;
    }

    public String getBackupsServerAddress() {
        return backupsServerAddress;
    }

    public void setBackupsServerAddress(String backupsServerAddress) {
        this.backupsServerAddress = backupsServerAddress;
    }

    public Short getServerTcpPort() {
        return serverTcpPort;
    }

    public void setServerTcpPort(Short serverTcpPort) {
        this.serverTcpPort = serverTcpPort;
    }

    public Short getServerUdpPort() {
        return serverUdpPort;
    }

    public void setServerUdpPort(Short serverUdpPort) {
        this.serverUdpPort = serverUdpPort;
    }
}
